package com.dituhui.gps.service;

import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.log4j.Logger;

import com.dituhui.gps.vo.GPSLine;
import com.dituhui.gps.vo.GPSPoint;
import com.dituhui.tool.io.Constants;
import com.dituhui.tool.io.ESTool;
import com.dituhui.tool.io.HttpTool;
import com.dituhui.tool.io.RedisTool;
import com.dituhui.tool.util.DateUtil;
import com.dituhui.tool.util.StringUtil;

/**
 * 查询轨迹类
 * 
 * @author liweigu
 * 
 */
public class GetTrack {
	private static Logger LOGGER = Logger.getLogger(GetTrack.class);
	private static String STR_SPLIT_TAG = Constants.getValue("STR_SPLIT_TAG");
	private static String TRACK_WEB_HOST = Constants.getValue("TRACK_WEB_HOST");
	private static String RealtimeES_IndexPrefix = Constants.getValue("RealtimeES_IndexPrefix", "gps_config.properties");
	private static String HistoryES_IndexPrefix = Constants.getValue("HistoryES_IndexPrefix", "gps_config.properties");
	private static final String Redis_Track_Prefix = "track_";

	public static String getRedisKey(String day, String accountId) {
		String redisKey;

		// if (groupId == null) {
		redisKey = GetTrack.Redis_Track_Prefix + day + StringUtil.Underline + accountId;
		// } else {
		// redisKey = GetTrack.Redis_Track_Prefix + day + StringUtil.Underline + groupId + StringUtil.Underline + accountId;
		// }

		return redisKey;
	}

	/**
	 * 获取轨迹
	 * 
	 * @param plateNumber 车牌号
	 * @param startDate 开始日期
	 * @param endDate 结束日期（时间跨度不允许超过10天）
	 * @return 车辆轨迹。哈希对象，key是含日期的index，value是该天的轨迹。
	 */
	private static HashMap<String, GPSLine> getTrack(String groupId, String plateNumber, String startDate, String endDate) {
		// TODO: 根据groupId筛选
		HashMap<String, GPSLine> tracks = null;
		// 服务地址
		// TRACK_WEB_HOST = "10.135.7.172:8725";
		String trackWebUrl = "http://" + TRACK_WEB_HOST + "/GPSTrackWeb/gps/search/track";
		// 处理plateNumber里的特殊字符，比如空格开头的，避免破坏http请求
		if (plateNumber != null && !plateNumber.equals("")) {
			plateNumber = plateNumber.replaceAll("_", "").replaceAll("%", "").replaceAll("|", "").replaceAll("\n", "").replaceAll("\r", "").replaceAll("\t",
					"");
			plateNumber = URLEncoder.encode(plateNumber);
			String param = "param={\"platenumber\":\"" + plateNumber + "\",\"starttime\":\"" + startDate + "\"";
			if (endDate != null) {
				param += ",\"endtime\":\"" + endDate + "\"";
			}
			param += "}";
			// param += "&testflag=printTime";
			// System.out.println("url = " + trackWebUrl + "?" + param);
			String subContent = null;
			try {
				String content = HttpTool.getContentByGET(trackWebUrl, param);
				// 如果调用服务有正常的返回结果，则进行new HashMap
				tracks = new HashMap<String, GPSLine>();
				// System.out.println("content = " + content);
				if (content.indexOf("[") != -1 && content.indexOf("]") > content.indexOf("[")) {
					subContent = content.substring(content.indexOf("[") + 1, content.lastIndexOf("]"));
					// System.out.println("subContent = " + subContent);

					String split_tag = "__";
					subContent = subContent.replaceAll("\\},\\{", "}" + split_tag + "{");
					// System.out.println("subContent = " + subContent);
					String[] infos = subContent.split(split_tag);
					for (String info : infos) {
						// System.out.println("info=" + info);
						// info的内容是null时跳过
						if (!StringUtil.NULL.endsWith(info)) {
							// 把字符串替换为json格式的，历史轨迹带有plateNumber，当天轨迹带有ssid
							info = info.replaceAll(STR_SPLIT_TAG, ",").replaceAll("infos\":\"", "infos\":\"[")
									.replaceAll("}\",\"plateNumber", "}]\",\"plateNumber").replaceAll("}\",\"ssid", "}]\",\"ssid");
							// System.out.println("info2=" + info);
							JSONObject jsonObject = JSONObject.fromObject(info);
							if (jsonObject.containsKey("_index")) {
								String index = jsonObject.getString("_index");
								JSONObject sourceJSONObject = jsonObject.getJSONObject("_source");
								if (sourceJSONObject.size() > 0) {
									try {
										JSONArray gpsPoints = sourceJSONObject.getJSONArray("infos");
										// System.out.println(index);
										// System.out.println(gpsPoints);
										GPSLine gpsLine = new GPSLine();
										for (int i = 0; i < gpsPoints.size(); i++) {
											String str = gpsPoints.getString(i);
											// System.out.println(str);
											GPSPoint gpsPoint = GPSPoint.parseCSVString(str);
											// 根据groupId筛选
											if (groupId == null || groupId.equals(gpsPoint.getGroupId())) {
												gpsLine.getGPSPoints().add(gpsPoint);
											}
										}
										// TODO: 按照日期先后排序
										tracks.put(index, gpsLine);
									} catch (Exception e) {
										String message = "getTrack里解析sourceJSONObject发生异常。";
										LOGGER.debug(message, e);
									}
								}
							}
						}
					}
				}
			} catch (Exception e) {
				String message = "getTrack发生异常。url = " + trackWebUrl + "?" + param;
				LOGGER.warn(message, e);
			}
		} else {
			// 如果车牌号为空，则创建空HashMap
			tracks = new HashMap<String, GPSLine>();
		}

		return tracks;
	}

	// /**
	// * 通过开始和结束时间获取GPS轨迹
	// *
	// * @param trackArray 轨迹数组
	// * @param startTime 开始时间
	// * @param endTime 结束时间
	// * @return GeoLine GPS轨迹
	// */
	// private GPSLine getTodayTracks(JSONArray trackArray, long startTime, long endTime) {
	// GPSLine geoLine = null;
	// if (trackArray != null && trackArray.size() > 2) {
	// geoLine = new GPSLine();
	// for (int i = 0; i < trackArray.size(); i++) {
	// String str = trackArray.getString(i);
	// GPSPoint gpsPoint = GPSPoint.parseCSVString(str);
	// Date dt2 = gpsPoint.getGPSTime();
	// // GPSTime为空的忽略
	// if (dt2 != null) {
	// // 继续转换得到秒数的long型
	// long currentPointTime = dt2.getTime() / 1000;
	// if (currentPointTime > endTime) {
	// break;
	// }
	// if (startTime < currentPointTime && currentPointTime < endTime) {
	// geoLine.getGPSPoints().add(gpsPoint);
	// }
	// }
	// }
	// }
	// return geoLine;
	// }

	/**
	 * 从redis获取当天轨迹
	 * 
	 * @param redisUrl redis服务地址
	 * @param redisPort redis服务端口
	 * @param redisPwd redis服务密码
	 * @param accountId 帐号ID
	 * @param groupId 组织ID
	 * @return 车辆轨迹
	 */
	public static GPSLine getGPSLineFromRedis(String redisUrl, int redisPort, String redisPwd, String accountId, String groupId, boolean sortByTime) {
		GPSLine gpsLine = null;

		try {
			// 当天日期
			Date todayDate = new Date();
			SimpleDateFormat dayFormat = new SimpleDateFormat("yyyyMMdd");
			String strTodayDate = dayFormat.format(todayDate);

			if (accountId != null && !accountId.equals("")) {
				// plateNumber = plateNumber.replaceAll("_", "").replaceAll("%", "").replaceAll("|", "").replaceAll("\n", "").replaceAll("\r", "")
				// .replaceAll("\t", "");
				String redisKey = GetTrack.getRedisKey(strTodayDate, accountId);
				String value = null;
				try {
					value = (new RedisTool()).getString(redisKey, redisUrl, redisPort, redisPwd);
				} catch (Exception e) {
					// try {
					// // LOGGER.info("读取redis超时了！！！在请求一次！"+key);
					// String slaveHost = "10.135.12.250";
					// infos = (new RedisTool()).getString(key, slaveHost);
					// } catch (Exception ee) {
					LOGGER.info("读取redis超时了。" + redisKey);
					e.printStackTrace();
					// }
				}
				if (value != null) {
					// System.out.println("value = " + value);
					gpsLine = new GPSLine();
					List<GPSPoint> gpsPoints = new ArrayList<GPSPoint>();

					// 去掉第一个是分隔符的字符
					if (value.startsWith(StringUtil.AngularBracket)) {
						value = value.substring(1);
					}
					String[] gpsArray = value.split(StringUtil.AngularBracketForSplit);
					for (String gps : gpsArray) {
						if (gps != null) {
							GPSPoint gpsPoint = GPSPoint.parseCSVString(gps);
							// 根据groupId筛选
							if (groupId == null || groupId.equals(gpsPoint.getGroupId())) {
								gpsPoints.add(gpsPoint);
							}
						}
					}

					// 排序
					if (sortByTime) {
						// GPSLine.sortByTime(gpsPoints);
						// FlySpotHandler.dealFlySpot(gpsPoints);
					}

					gpsLine.setGPSPoints(gpsPoints);
				}
			}
		} catch (Exception e) {
			LOGGER.warn("读取redis轨迹发生异常:" + e.getMessage());
		}

		return gpsLine;
	}

	/**
	 * 从ES实时获取某天全部车辆轨迹
	 * 
	 * @param date 日期
	 * @param realtimeESUrl ES服务地址
	 * @return 车辆轨迹。key是账号id，value是轨迹。
	 */
	public static HashMap<String, GPSLine> getGPSLineFromRealtimeES(String date, String realtimeESUrl) {
		HashMap<String, GPSLine> gpsLines = new HashMap<String, GPSLine>();

		String index = RealtimeES_IndexPrefix + date;
		String[] queryColumnNames = null;
		String[] queryColumnValues = null;
		List<String> dataList = ESTool.query(index, queryColumnNames, queryColumnValues, realtimeESUrl);
		for (String data : dataList) {
			// {"gps":"李玮顾,null,,2016-12-22
			// 21:10:18,,104.067955,30.537390,104.067955,30.537390,0,0.0,120.0,null,0,30,0.0,null....","plateNumber":"null","aid":"李玮顾"}
			JSONObject jsonObject = JSONObject.fromObject(data);
			String gpsString = jsonObject.getString("gps");
			// String groupId;
			// if (jsonObject.containsKey("groupId")) {
			// groupId = jsonObject.getString("groupId");
			// } else {
			// groupId = null;
			// }
			GPSPoint gpsPoint = GPSPoint.parseCSVString(gpsString);
			if (gpsPoint != null) {
				String accountId = gpsPoint.getAccountId();
				if (accountId != null) {
					GPSLine gpsLine = gpsLines.get(accountId);
					if (gpsLine == null) {
						// 第一次为空，创建对象。
						gpsLine = new GPSLine();
					}
					gpsLine.getGPSPoints().add(gpsPoint);
					// gpsLine.setGroupId(groupId);
					gpsLines.put(accountId, gpsLine);
				}
			}
		}

		return gpsLines;
	}

	/**
	 * 从ES历史获取某天全部车辆轨迹
	 *
	 * @param accountId 账号ID
	 * @param groupId 组织ID
	 * @param date 日期
	 * @param historyESUrl ES服务地址
	 * @return 车辆轨迹。key是账号轨迹日期（年月日），value是轨迹。
	 */
	public static Map<String, String> getGPSLineFromHistoryES(String accountId, String groupId, String startDate, String endDate, String historyESUrl) {
		Map<String, String> results = new HashMap<String, String>();
		String index;
		try {
			index = makeIndex(startDate, endDate);
			// LOGGER.info("index=" + index);
		} catch (ParseException e) {
			String message = "日期参数非法";
			throw new IllegalArgumentException(message, e);
		}
		// System.out.println("index=" + index);
		String[] queryColumnNames;
		String[] queryColumnValues;
		// if (groupId == null) {
		queryColumnNames = new String[] { "accountID" };
		queryColumnValues = new String[] { accountId };
		// } else {
		// queryColumnNames = new String[] { "accountID", "groupId" };
		// queryColumnValues = new String[] { accountId, groupId };
		// }
		List<Map<String, Object>> mapList = ESTool.queryToMapList(index, queryColumnNames, queryColumnValues, historyESUrl);
		for (Map<String, Object> map : mapList) {
			Map<String, String> sourceMap = (Map<String, String>) map.get("_source");
			String currentIndex = (String) map.get("_index");
			// LOGGER.info("currentIndex=" + currentIndex);
			String date = currentIndex.replaceAll(HistoryES_IndexPrefix, "");
			// LOGGER.info("date=" + date);
			String infos = sourceMap.get("infos");
//			LOGGER.info("infos=" + infos);
			if (groupId != null && groupId.length() > 0) {
				if (infos.contains(StringUtil.DoubleUnderline)) {
					// 分隔符格式
					String[] gpsPointArray = infos.split(StringUtil.DoubleUnderline);
					StringBuilder gpsPoints2 = new StringBuilder();
					boolean isFirst = true;
					for (String str : gpsPointArray) {
						GPSPoint gpsPoint = GPSPoint.parseCSVString(str);
						// 根据groupId筛选
						if (groupId.equals(gpsPoint.getGroupId())) {
							gpsPoints2.append(str);
							if (isFirst) {
								isFirst = false;
							} else {
								gpsPoints2.append(StringUtil.DoubleUnderline);
							}
						}
						infos = gpsPoints2.toString();
					}
				} else {
					// JSON格式。TODO: 验证是否会进入此分支。
					JSONArray gpsPointArray = JSONArray.fromObject(infos);
					// System.out.println(gpsPoints);
					JSONArray gpsPoints2 = new JSONArray();
					for (int i = 0; i < gpsPointArray.size(); i++) {
						String str = gpsPointArray.getString(i);
						// System.out.println(str);
						GPSPoint gpsPoint = GPSPoint.parseCSVString(str);
						// 根据groupId筛选
						if (groupId.equals(gpsPoint.getGroupId())) {
							gpsPoints2.add(str);
						}
					}
					JSONArray gpsPointArray2 = JSONArray.fromObject(gpsPoints2);
					infos = gpsPointArray2.toString();
				}
			}
			// LOGGER.info("(getGPSLineFromHistoryES)infos=" + infos);
			results.put(date, infos);
		}

		return results;
	}

	/***
	 * 根据日期跨度获取索引
	 * 
	 * @return
	 * @throws ParseException
	 */
	protected static String makeIndex(String startDate, String endDate) throws ParseException {
		StringBuffer passTime_buffer_ = new StringBuffer();

		passTime_buffer_.append(HistoryES_IndexPrefix).append(startDate); // 加入起始日期

		SimpleDateFormat format = DateUtil.getDayFormat();
		Date date_start_ = null;
		Date date_end_ = null;

		if (endDate != null && !endDate.equals("")) { // 结束日期不为空，按连续日期计算
			date_start_ = format.parse(startDate);
			date_end_ = format.parse(endDate);

			Calendar cal = Calendar.getInstance();
			cal.setTime(date_start_); // 设置起始日期

			boolean bContinue = true;

			while (bContinue) {
				// 根据日历的规则，为给定的日历字段添加或减去指定的时间量
				cal.add(Calendar.DAY_OF_MONTH, 1);
				// 测试此日期是否在指定日期之后
				if (date_end_.after(cal.getTime())) {
					passTime_buffer_.append(",").append(HistoryES_IndexPrefix).append(format.format(cal.getTime()));
				} else {
					break;
				} // if..else
			} // while

			// 拼接最后一天
			passTime_buffer_.append(StringUtil.COMMA).append(HistoryES_IndexPrefix).append(endDate);

		} // if

		return passTime_buffer_.toString();
	}

	// public static class GPSLineWithUserInfo extends GPSLine {
	// private String groupId;
	//
	// public String getGroupId() {
	// return groupId;
	// }
	//
	// public void setGroupId(String groupId) {
	// this.groupId = groupId;
	// }
	// }

}
